package com.ygswglxt.attendance.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ygswglxt.attendance.entity.AttendanceRecord;
import com.ygswglxt.attendance.entity.AttendanceRule;
import com.ygswglxt.attendance.entity.AttendanceSupplement;
import com.ygswglxt.attendance.mapper.AttendanceMapper;
import com.ygswglxt.attendance.mapper.AttendanceRuleMapper;
import com.ygswglxt.attendance.mapper.AttendanceSupplementMapper;
import com.ygswglxt.common.Result;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletResponse;
import java.sql.Time;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class AttendanceService {
    
    @Autowired
    private AttendanceMapper attendanceMapper;
    
    @Autowired
    private AttendanceRuleMapper attendanceRuleMapper;
    
    @Autowired
    private AttendanceSupplementMapper attendanceSupplementMapper;
    
    @Autowired(required = false)
    private RocketMQTemplate rocketMQTemplate;
    
    private RestTemplate restTemplate = new RestTemplate();
    private static final String NOTIFICATION_SERVICE_URL = "http://localhost:8086/notification/create";
    private static final String USER_SERVICE_URL = "http://localhost:8082/user/managers";
    
    // 查询所有经理ID（用于发送审批通知）
    private List<Long> getManagerIds() {
        try {
            Result result = restTemplate.getForObject(USER_SERVICE_URL, Result.class);
            if (result != null && result.getCode() != null && result.getCode().equals(200)) {
                List<Map<String, Object>> managers = (List<Map<String, Object>>) result.getData();
                List<Long> managerIds = new ArrayList<>();
                for (Map<String, Object> manager : managers) {
                    Long id = ((Number) manager.get("id")).longValue();
                    managerIds.add(id);
                }
                return managerIds;
            }
        } catch (Exception e) {
            System.err.println("查询经理列表失败: " + e.getMessage());
        }
        return new ArrayList<>();
    }
    
    // 备用方案：直接通过HTTP调用通知服务
    private void createNotificationDirectly(Long userId, String type, String title, String content, Long relatedId, String relatedType) {
        try {
            Map<String, Object> params = new HashMap<>();
            params.put("userId", userId);
            params.put("type", type);
            params.put("title", title);
            params.put("content", content);
            if (relatedId != null) {
                params.put("relatedId", relatedId);
            }
            if (relatedType != null) {
                params.put("relatedType", relatedType);
            }
            
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            HttpEntity<String> request = new HttpEntity<>(com.alibaba.fastjson.JSON.toJSONString(params), headers);
            
            restTemplate.postForObject(NOTIFICATION_SERVICE_URL, request, Result.class);
            System.out.println("✓ 通过HTTP直接创建通知成功 - userId: " + userId + ", type: " + type);
        } catch (Exception e) {
            System.err.println("❌ HTTP直接创建通知失败: " + e.getMessage());
            e.printStackTrace();
        }
    }
    
    // 获取当前生效的考勤规则
    private AttendanceRule getActiveRule() {
        QueryWrapper<AttendanceRule> wrapper = new QueryWrapper<>();
        wrapper.eq("status", "ACTIVE");
        wrapper.last("LIMIT 1");
        AttendanceRule rule = attendanceRuleMapper.selectOne(wrapper);
        if (rule == null) {
            // 如果没有配置，使用默认规则
            rule = new AttendanceRule();
            rule.setWorkStartTime(Time.valueOf("09:00:00"));
            rule.setWorkEndTime(Time.valueOf("18:00:00"));
            rule.setLateThreshold(15);
            rule.setEarlyLeaveThreshold(15);
        }
        return rule;
    }
    
    // 检测考勤异常
    private void checkAttendanceException(AttendanceRecord record, AttendanceRule rule) {
        Date checkInTime = record.getCheckInTime();
        Date checkOutTime = record.getCheckOutTime();
        Date attendanceDate = record.getAttendanceDate();
        
        if (attendanceDate == null && checkInTime != null) {
            attendanceDate = new Date(checkInTime.getTime());
            // 只保留日期部分
            Calendar cal = Calendar.getInstance();
            cal.setTime(attendanceDate);
            cal.set(Calendar.HOUR_OF_DAY, 0);
            cal.set(Calendar.MINUTE, 0);
            cal.set(Calendar.SECOND, 0);
            cal.set(Calendar.MILLISECOND, 0);
            attendanceDate = cal.getTime();
            record.setAttendanceDate(attendanceDate);
        }
        
        // 检测迟到
        if (checkInTime != null && rule.getWorkStartTime() != null) {
            Calendar checkInCal = Calendar.getInstance();
            checkInCal.setTime(checkInTime);
            
            Calendar workStartCal = Calendar.getInstance();
            workStartCal.setTime(attendanceDate != null ? attendanceDate : checkInTime);
            Time workStart = rule.getWorkStartTime();
            workStartCal.set(Calendar.HOUR_OF_DAY, workStart.getHours());
            workStartCal.set(Calendar.MINUTE, workStart.getMinutes());
            workStartCal.set(Calendar.SECOND, 0);
            workStartCal.set(Calendar.MILLISECOND, 0);
            
            long diffMinutes = (checkInCal.getTimeInMillis() - workStartCal.getTimeInMillis()) / (1000 * 60);
            if (diffMinutes > rule.getLateThreshold()) {
                record.setIsLate(true);
                record.setLateMinutes((int) diffMinutes);
                record.setExceptionReason("迟到 " + diffMinutes + " 分钟");
            } else {
                record.setIsLate(false);
                record.setLateMinutes(0);
            }
        }
        
        // 检测早退
        if (checkOutTime != null && rule.getWorkEndTime() != null) {
            Calendar checkOutCal = Calendar.getInstance();
            checkOutCal.setTime(checkOutTime);
            
            Calendar workEndCal = Calendar.getInstance();
            workEndCal.setTime(attendanceDate != null ? attendanceDate : checkOutTime);
            Time workEnd = rule.getWorkEndTime();
            workEndCal.set(Calendar.HOUR_OF_DAY, workEnd.getHours());
            workEndCal.set(Calendar.MINUTE, workEnd.getMinutes());
            workEndCal.set(Calendar.SECOND, 0);
            workEndCal.set(Calendar.MILLISECOND, 0);
            
            long diffMinutes = (workEndCal.getTimeInMillis() - checkOutCal.getTimeInMillis()) / (1000 * 60);
            if (diffMinutes > rule.getEarlyLeaveThreshold()) {
                record.setIsEarlyLeave(true);
                record.setEarlyLeaveMinutes((int) diffMinutes);
                if (record.getExceptionReason() == null) {
                    record.setExceptionReason("早退 " + diffMinutes + " 分钟");
                } else {
                    record.setExceptionReason(record.getExceptionReason() + "，早退 " + diffMinutes + " 分钟");
                }
            } else {
                record.setIsEarlyLeave(false);
                record.setEarlyLeaveMinutes(0);
            }
        }
    }
    
    public Result<String> checkIn(Long userId) {
        try {
            AttendanceRule rule = getActiveRule();
            Date now = new Date();
            
            AttendanceRecord record = new AttendanceRecord();
            record.setUserId(userId);
            record.setCheckInTime(now);
            record.setType("CHECK_IN");
            record.setStatus("APPROVED");
            record.setCreateTime(now);
            record.setAttendanceDate(now);
            
            // 检测异常
            checkAttendanceException(record, rule);
            
            int result = attendanceMapper.insert(record);
            if (result <= 0) {
                return Result.error("打卡失败");
            }
            
            // 发送MQ消息通知（如果RocketMQ可用）
            boolean mqSuccess = false;
            if (rocketMQTemplate != null) {
                try {
                    Map<String, Object> message = new HashMap<>();
                    message.put("userId", userId);
                    message.put("type", "CHECK_IN");
                    message.put("time", new Date().getTime());
                    rocketMQTemplate.convertAndSend("attendance-topic", com.alibaba.fastjson.JSON.toJSONString(message));
                    mqSuccess = true;
                } catch (Exception e) {
                    // MQ发送失败，使用备用方案
                    System.err.println("MQ消息发送失败，使用HTTP备用方案: " + e.getMessage());
                }
            }
            
            // 如果MQ发送失败，使用HTTP直接调用通知服务（备用方案）
            if (!mqSuccess) {
                createNotificationDirectly(
                    userId,
                    "ATTENDANCE",
                    "打卡提醒",
                    "您已成功打卡上班",
                    record.getId(),
                    "ATTENDANCE"
                );
            }
            
            return Result.success("打卡成功");
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error("打卡失败: " + e.getMessage());
        }
    }
    
    public Result<String> checkOut(Long userId) {
        try {
            AttendanceRule rule = getActiveRule();
            Date now = new Date();
            
            AttendanceRecord record = new AttendanceRecord();
            record.setUserId(userId);
            record.setCheckOutTime(now);
            record.setType("CHECK_OUT");
            record.setStatus("APPROVED");
            record.setCreateTime(now);
            record.setAttendanceDate(now);
            
            // 检测异常
            checkAttendanceException(record, rule);
            
            int result = attendanceMapper.insert(record);
            if (result <= 0) {
                return Result.error("打卡失败");
            }
            
            // 发送MQ消息通知（如果RocketMQ可用）
            boolean mqSuccess = false;
            if (rocketMQTemplate != null) {
                try {
                    Map<String, Object> message = new HashMap<>();
                    message.put("userId", userId);
                    message.put("type", "CHECK_OUT");
                    message.put("time", new Date().getTime());
                    rocketMQTemplate.convertAndSend("attendance-topic", com.alibaba.fastjson.JSON.toJSONString(message));
                    mqSuccess = true;
                } catch (Exception e) {
                    // MQ发送失败，使用备用方案
                    System.err.println("MQ消息发送失败，使用HTTP备用方案: " + e.getMessage());
                }
            }
            
            // 如果MQ发送失败，使用HTTP直接调用通知服务（备用方案）
            if (!mqSuccess) {
                createNotificationDirectly(
                    userId,
                    "ATTENDANCE",
                    "打卡提醒",
                    "您已成功打卡下班",
                    record.getId(),
                    "ATTENDANCE"
                );
            }
            
            return Result.success("下班打卡成功");
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error("打卡失败: " + e.getMessage());
        }
    }
    
    public Result<String> overtime(Long userId, Integer hours, String date, String reason) {
        try {
            AttendanceRecord record = new AttendanceRecord();
            record.setUserId(userId);
            record.setType("OVERTIME");
            record.setStatus("PENDING");
            record.setCreateTime(new Date());
            
            // 设置加班时长
            if (hours != null && hours > 0) {
                record.setHours(new java.math.BigDecimal(hours));
            }
            
            // 设置加班日期
            if (date != null && !date.isEmpty()) {
                try {
                    java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd");
                    sdf.setLenient(false); // 严格模式
                    Date overtimeDate = sdf.parse(date);
                    record.setOvertimeDate(overtimeDate);
                    // 同时设置checkInTime用于兼容（如果overtime_date字段不存在）
                    record.setCheckInTime(overtimeDate);
                } catch (Exception e) {
                    // 解析失败则使用当前时间
                    e.printStackTrace();
                    Date now = new Date();
                    record.setOvertimeDate(now);
                    record.setCheckInTime(now);
                }
            } else {
                Date now = new Date();
                record.setOvertimeDate(now);
                record.setCheckInTime(now);
            }
            
            // 设置加班原因
            if (reason != null && !reason.isEmpty()) {
                record.setReason(reason);
            }
            
            int result = attendanceMapper.insert(record);
            if (result <= 0) {
                return Result.error("保存失败");
            }
            
            // 发送MQ消息通知（如果RocketMQ可用）
            boolean mqSuccess = false;
            if (rocketMQTemplate != null) {
                try {
                    Map<String, Object> message = new HashMap<>();
                    message.put("userId", userId);
                    message.put("type", "OVERTIME");
                    message.put("recordId", record.getId());
                    message.put("hours", hours);
                    message.put("date", date);
                    message.put("reason", reason);
                    message.put("time", new Date().getTime());
                    rocketMQTemplate.convertAndSend("attendance-topic", com.alibaba.fastjson.JSON.toJSONString(message));
                    mqSuccess = true;
                } catch (Exception e) {
                    // MQ发送失败，使用备用方案
                    System.err.println("MQ消息发送失败，使用HTTP备用方案: " + e.getMessage());
                }
            }
            
            // 如果MQ发送失败，使用HTTP直接调用通知服务（备用方案）
            if (!mqSuccess) {
                // 查询所有经理，给每个经理发送通知
                List<Long> managerIds = getManagerIds();
                if (managerIds.isEmpty()) {
                    System.err.println("⚠️ 未找到经理，无法发送审批通知");
                } else {
                    for (Long managerId : managerIds) {
                        createNotificationDirectly(
                            managerId,
                            "APPROVAL_PENDING",
                            "待审批：加班申请",
                            "您有新的加班申请需要审批，时长：" + hours + "小时，日期：" + date,
                            record.getId(),
                            "OVERTIME"
                        );
                    }
                }
            }
            
            return Result.success("加班申请已提交");
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error("提交失败: " + e.getMessage());
        }
    }
    
    // 获取用户的加班记录
    public Result<List<AttendanceRecord>> getMyOvertimeRecords(Long userId) {
        QueryWrapper<AttendanceRecord> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id", userId);
        wrapper.eq("type", "OVERTIME");
        wrapper.orderByDesc("create_time");
        List<AttendanceRecord> records = attendanceMapper.selectList(wrapper);
        return Result.success(records);
    }
    
    public Result<List<AttendanceRecord>> getMyRecords(Long userId) {
        QueryWrapper<AttendanceRecord> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id", userId);
        wrapper.orderByDesc("create_time");
        List<AttendanceRecord> records = attendanceMapper.selectList(wrapper);
        return Result.success(records);
    }
    
    public Result<List<AttendanceRecord>> getAllRecords() {
        List<AttendanceRecord> records = attendanceMapper.selectList(null);
        return Result.success(records);
    }
    
    // 审批加班
    public Result<String> approveOvertime(Long recordId, Long approverId, String status) {
        AttendanceRecord record = attendanceMapper.selectById(recordId);
        if (record == null) {
            return Result.error(404, "记录不存在");
        }
        if (!"OVERTIME".equals(record.getType())) {
            return Result.error(400, "该记录不是加班申请");
        }
        if (!"PENDING".equals(record.getStatus())) {
            return Result.error(400, "该申请已处理");
        }
        
        record.setStatus(status);
        attendanceMapper.updateById(record);
        
        // 发送MQ消息通知审批结果（如果RocketMQ可用）
        boolean mqSuccess = false;
        if (rocketMQTemplate != null) {
            try {
                Map<String, Object> message = new HashMap<>();
                message.put("userId", record.getUserId());
                message.put("type", "OVERTIME_APPROVE");
                message.put("recordId", recordId);
                message.put("status", status);
                message.put("approverId", approverId);
                message.put("hours", record.getHours() != null ? record.getHours().toString() : "");
                rocketMQTemplate.convertAndSend("attendance-topic", com.alibaba.fastjson.JSON.toJSONString(message));
                mqSuccess = true;
            } catch (Exception e) {
                // MQ发送失败，使用备用方案
                System.err.println("MQ消息发送失败，使用HTTP备用方案: " + e.getMessage());
            }
        }
        
        // 如果MQ发送失败，使用HTTP直接调用通知服务（备用方案）
        if (!mqSuccess) {
            String statusName = "APPROVED".equals(status) ? "已通过" : "已拒绝";
            String hoursStr = record.getHours() != null ? record.getHours().toString() + "小时" : "";
            createNotificationDirectly(
                record.getUserId(),
                "APPROVAL_RESULT",
                "审批结果：加班申请",
                "您的加班申请（" + hoursStr + "）" + statusName,
                recordId,
                "OVERTIME"
            );
        }
        
        return Result.success("审批完成");
    }
    
    // 获取待审批的加班申请（包含员工名称）
    public Result<List<AttendanceRecord>> getPendingOvertime() {
        List<AttendanceRecord> records = attendanceMapper.selectPendingOvertimeWithUserName();
        return Result.success(records);
    }
    
    // 获取下属考勤记录（经理查看，包含员工名称）
    public Result<List<AttendanceRecord>> getSubordinateRecords(Long managerId) {
        // 这里简化处理，实际应该根据组织架构查询下属
        // 暂时返回所有考勤记录（包含员工名称），实际应该关联用户表查询下属
        List<AttendanceRecord> records = attendanceMapper.selectSubordinateRecordsWithUserName();
        return Result.success(records);
    }
    
    // 导出团队考勤记录
    public void exportSubordinateRecords(HttpServletResponse response, Long managerId) throws Exception {
        Result<List<AttendanceRecord>> recordsResult = getSubordinateRecords(managerId);
        List<AttendanceRecord> records = recordsResult.getData();
        if (records == null) {
            records = new ArrayList<>();
        }
        
        // 准备导出数据
        List<Map<String, Object>> exportData = new ArrayList<>();
        SimpleDateFormat dateTimeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        
        for (AttendanceRecord record : records) {
            Map<String, Object> row = new HashMap<>();
            row.put("userName", record.getUserName() != null ? record.getUserName() : "员工" + record.getUserId());
            
            // 考勤类型
            String typeName = "";
            if ("CHECK_IN".equals(record.getType())) {
                typeName = "上班";
            } else if ("CHECK_OUT".equals(record.getType())) {
                typeName = "下班";
            } else if ("OVERTIME".equals(record.getType())) {
                typeName = "加班";
            }
            row.put("type", typeName);
            
            // 打卡时间
            String checkTime = "";
            if (record.getCheckInTime() != null) {
                checkTime = dateTimeFormat.format(record.getCheckInTime());
            } else if (record.getCheckOutTime() != null) {
                checkTime = dateTimeFormat.format(record.getCheckOutTime());
            } else if (record.getOvertimeDate() != null) {
                checkTime = dateTimeFormat.format(record.getOvertimeDate());
            }
            row.put("checkTime", checkTime);
            
            // 加班时长（仅加班类型显示）
            if ("OVERTIME".equals(record.getType()) && record.getHours() != null) {
                row.put("hours", record.getHours().toString() + "小时");
            } else {
                row.put("hours", "");
            }
            
            // 加班原因（仅加班类型显示）
            if ("OVERTIME".equals(record.getType())) {
                row.put("reason", record.getReason() != null ? record.getReason() : "");
            } else {
                row.put("reason", "");
            }
            
            // 状态
            String statusName = "待审核";
            if (record.getStatus() != null) {
                if ("APPROVED".equals(record.getStatus())) {
                    statusName = "已通过";
                } else if ("REJECTED".equals(record.getStatus())) {
                    statusName = "已拒绝";
                }
            }
            row.put("status", statusName);
            
            row.put("createTime", record.getCreateTime() != null ? dateTimeFormat.format(record.getCreateTime()) : "");
            
            exportData.add(row);
        }
        
        // 表头
        String[] headers = {"员工姓名", "考勤类型", "打卡时间", "加班时长", "加班原因", "状态", "创建时间"};
        String[] fieldNames = {"userName", "type", "checkTime", "hours", "reason", "status", "createTime"};
        
        // 导出Excel
        com.ygswglxt.attendance.util.ExcelExportUtil.exportExcel(
            response, 
            "团队考勤记录", 
            headers, 
            exportData, 
            fieldNames
        );
    }
    
    // 考勤统计（HR使用）
    public Result<Map<String, Object>> getAttendanceStatistics(String month) {
        try {
            // 如果没有指定月份，使用当前月份
            if (month == null || month.isEmpty()) {
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
                month = sdf.format(new Date());
            }
            
            Map<String, Object> result = new HashMap<>();
            
            // 1. 统计总体数据
            // 总打卡次数（CHECK_IN和CHECK_OUT）
            QueryWrapper<AttendanceRecord> checkInWrapper = new QueryWrapper<>();
            checkInWrapper.in("type", Arrays.asList("CHECK_IN", "CHECK_OUT"));
            if (month != null && !month.isEmpty()) {
                checkInWrapper.apply("DATE_FORMAT(create_time, '%Y-%m') = {0}", month);
            }
            Long totalCheckIns = attendanceMapper.selectCount(checkInWrapper);
            
            // 正常出勤人数（有打卡记录的用户数）
            List<Map<String, Object>> checkInStats = attendanceMapper.selectCheckInCountByMonth(month);
            Long normalAttendance = (long) checkInStats.size();
            
            // 请假人数（查询leave_record表，统计该月有请假记录的用户数）
            Long leaveCount = 0L;
            try {
                Long leaveUserCount = attendanceMapper.selectLeaveUserCountByMonth(month);
                leaveCount = leaveUserCount != null ? leaveUserCount : 0L;
            } catch (Exception e) {
                // 如果查询失败（可能是表不存在或权限问题），设为0
                System.err.println("查询请假数据失败: " + e.getMessage());
                leaveCount = 0L;
            }
            
            // 加班人次（已通过的加班申请）
            QueryWrapper<AttendanceRecord> overtimeWrapper = new QueryWrapper<>();
            overtimeWrapper.eq("type", "OVERTIME");
            overtimeWrapper.eq("status", "APPROVED");
            if (month != null && !month.isEmpty()) {
                overtimeWrapper.apply("DATE_FORMAT(create_time, '%Y-%m') = {0}", month);
            }
            Long overtimeCount = attendanceMapper.selectCount(overtimeWrapper);
            
            Map<String, Object> statistics = new HashMap<>();
            statistics.put("totalCheckIns", totalCheckIns);
            statistics.put("normalAttendance", normalAttendance);
            statistics.put("leaveCount", leaveCount);
            statistics.put("overtimeCount", overtimeCount);
            
            // 2. 统计每个员工的详细数据
            List<Map<String, Object>> details = new ArrayList<>();
            
            // 获取所有用户（简化处理，实际应该只获取有考勤记录的用户）
            QueryWrapper<AttendanceRecord> allWrapper = new QueryWrapper<>();
            if (month != null && !month.isEmpty()) {
                allWrapper.apply("DATE_FORMAT(create_time, '%Y-%m') = {0}", month);
            }
            List<AttendanceRecord> allRecords = attendanceMapper.selectList(allWrapper);
            
            // 获取打卡统计（按用户分组）
            List<Map<String, Object>> checkInStatsList = attendanceMapper.selectCheckInCountByMonth(month);
            Map<Long, Integer> checkInCountMap = new HashMap<>();
            for (Map<String, Object> stat : checkInStatsList) {
                Long userId = ((Number) stat.get("user_id")).longValue();
                Integer count = ((Number) stat.get("checkInCount")).intValue();
                checkInCountMap.put(userId, count);
            }
            
            // 获取加班统计（按用户分组）
            List<Map<String, Object>> overtimeStatsList = attendanceMapper.selectOvertimeByMonth(month);
            Map<Long, Double> overtimeHoursMap = new HashMap<>();
            for (Map<String, Object> stat : overtimeStatsList) {
                Long userId = ((Number) stat.get("user_id")).longValue();
                Double hours = ((Number) stat.get("totalHours")).doubleValue();
                overtimeHoursMap.put(userId, hours);
            }
            
            // 获取请假统计（按用户分组）
            Map<Long, Integer> leaveDaysMap = new HashMap<>();
            try {
                List<Map<String, Object>> leaveStatsList = attendanceMapper.selectLeaveDaysByMonth(month);
                for (Map<String, Object> stat : leaveStatsList) {
                    Long userId = ((Number) stat.get("user_id")).longValue();
                    Integer days = ((Number) stat.get("totalDays")).intValue();
                    leaveDaysMap.put(userId, days);
                }
            } catch (Exception e) {
                System.err.println("查询请假天数失败: " + e.getMessage());
            }
            
            // 获取所有有考勤记录的用户（联表查询用户名称）
            QueryWrapper<AttendanceRecord> userWrapper = new QueryWrapper<>();
            if (month != null && !month.isEmpty()) {
                userWrapper.apply("DATE_FORMAT(create_time, '%Y-%m') = {0}", month);
            }
            userWrapper.select("DISTINCT user_id");
            List<AttendanceRecord> userRecords = attendanceMapper.selectList(userWrapper);
            
            // 获取用户信息（通过联表查询）
            Set<Long> userIds = new HashSet<>();
            for (AttendanceRecord record : userRecords) {
                userIds.add(record.getUserId());
            }
            
            // 为每个用户创建统计记录
            for (Long userId : userIds) {
                Map<String, Object> userStat = new HashMap<>();
                userStat.put("userId", userId);
                
                // 获取用户名称（通过查询一条记录获取）
                QueryWrapper<AttendanceRecord> nameWrapper = new QueryWrapper<>();
                nameWrapper.eq("user_id", userId);
                nameWrapper.last("LIMIT 1");
                AttendanceRecord sampleRecord = attendanceMapper.selectOne(nameWrapper);
                if (sampleRecord != null && sampleRecord.getUserName() != null) {
                    userStat.put("userName", sampleRecord.getUserName());
                } else {
                    // 如果无法获取，尝试通过联表查询
                    List<AttendanceRecord> recordsWithName = attendanceMapper.selectSubordinateRecordsWithUserName();
                    for (AttendanceRecord r : recordsWithName) {
                        if (r.getUserId().equals(userId) && r.getUserName() != null) {
                            userStat.put("userName", r.getUserName());
                            break;
                        }
                    }
                }
                
                userStat.put("checkInCount", checkInCountMap.getOrDefault(userId, 0));
                userStat.put("leaveDays", leaveDaysMap.getOrDefault(userId, 0));
                userStat.put("overtimeHours", overtimeHoursMap.getOrDefault(userId, 0.0));
                
                // 计算出勤率
                int checkInCount = checkInCountMap.getOrDefault(userId, 0);
                int leaveDays = leaveDaysMap.getOrDefault(userId, 0);
                int workDays = 22; // 假设每月22个工作日
                // 出勤率 = (工作日数 - 请假天数) / 工作日数 * 100
                double attendanceRate = workDays > 0 ? ((workDays - leaveDays) / (double) workDays * 100) : 0;
                attendanceRate = Math.min(100, Math.max(0, attendanceRate));
                userStat.put("attendanceRate", Math.round(attendanceRate));
                
                details.add(userStat);
            }
            
            result.put("statistics", statistics);
            result.put("details", details);
            
            return Result.success(result);
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error("统计失败: " + e.getMessage());
        }
    }
    
    // 获取考勤规则列表
    public Result<List<AttendanceRule>> getAttendanceRules() {
        try {
            List<AttendanceRule> rules = attendanceRuleMapper.selectList(null);
            return Result.success(rules);
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error("获取考勤规则失败: " + e.getMessage());
        }
    }
    
    // 创建或更新考勤规则
    public Result<String> saveAttendanceRule(AttendanceRule rule) {
        try {
            if (rule.getId() == null) {
                rule.setStatus("ACTIVE");
                attendanceRuleMapper.insert(rule);
                return Result.success("创建成功");
            } else {
                attendanceRuleMapper.updateById(rule);
                return Result.success("更新成功");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error("保存失败: " + e.getMessage());
        }
    }
    
    // 申请补卡
    public Result<String> applySupplement(Long userId, String date, String type, String time, String reason) {
        try {
            AttendanceSupplement supplement = new AttendanceSupplement();
            supplement.setUserId(userId);
            
            // 解析日期
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
            supplement.setAttendanceDate(dateFormat.parse(date));
            
            // 解析时间
            SimpleDateFormat timeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String dateTimeStr = date + " " + time;
            supplement.setSupplementTime(timeFormat.parse(dateTimeStr));
            
            supplement.setSupplementType(type);
            supplement.setReason(reason);
            supplement.setStatus("PENDING");
            supplement.setCreateTime(new Date());
            
            attendanceSupplementMapper.insert(supplement);
            return Result.success("补卡申请已提交");
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error("提交失败: " + e.getMessage());
        }
    }
    
    // 获取我的补卡申请
    public Result<List<AttendanceSupplement>> getMySupplements(Long userId) {
        try {
            QueryWrapper<AttendanceSupplement> wrapper = new QueryWrapper<>();
            wrapper.eq("user_id", userId);
            wrapper.orderByDesc("create_time");
            List<AttendanceSupplement> supplements = attendanceSupplementMapper.selectList(wrapper);
            return Result.success(supplements);
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error("获取补卡申请失败: " + e.getMessage());
        }
    }
    
    // 获取待审批的补卡申请
    public Result<List<AttendanceSupplement>> getPendingSupplements() {
        try {
            List<AttendanceSupplement> supplements = attendanceSupplementMapper.selectPendingWithUserName();
            return Result.success(supplements);
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error("获取待审批补卡申请失败: " + e.getMessage());
        }
    }
    
    // 审批补卡申请
    public Result<String> approveSupplement(Long supplementId, Long approverId, String status, String remark) {
        try {
            AttendanceSupplement supplement = attendanceSupplementMapper.selectById(supplementId);
            if (supplement == null) {
                return Result.error("补卡申请不存在");
            }
            if (!"PENDING".equals(supplement.getStatus())) {
                return Result.error("该申请已处理");
            }
            
            supplement.setStatus(status);
            supplement.setApproverId(approverId);
            supplement.setApproveTime(new Date());
            supplement.setApproveRemark(remark);
            
            attendanceSupplementMapper.updateById(supplement);
            
            // 如果审批通过，创建考勤记录
            if ("APPROVED".equals(status)) {
                AttendanceRecord record = new AttendanceRecord();
                record.setUserId(supplement.getUserId());
                record.setAttendanceDate(supplement.getAttendanceDate());
                
                if ("CHECK_IN".equals(supplement.getSupplementType())) {
                    record.setCheckInTime(supplement.getSupplementTime());
                } else if ("CHECK_OUT".equals(supplement.getSupplementType())) {
                    record.setCheckOutTime(supplement.getSupplementTime());
                }
                
                record.setType(supplement.getSupplementType());
                record.setStatus("APPROVED");
                record.setReason("补卡：" + supplement.getReason());
                record.setCreateTime(new Date());
                
                // 检测异常
                AttendanceRule rule = getActiveRule();
                checkAttendanceException(record, rule);
                
                attendanceMapper.insert(record);
            }
            
            return Result.success("审批完成");
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error("审批失败: " + e.getMessage());
        }
    }
    
    // 获取异常考勤记录（支持更多筛选条件）
    public Result<List<AttendanceRecord>> getExceptionRecords(Long userId, String month, String exceptionType, String exceptionStatus) {
        try {
            // 使用联表查询方法，自动获取用户名
            List<AttendanceRecord> records = attendanceMapper.selectExceptionRecordsWithUserName(userId, month, exceptionType, exceptionStatus);
            return Result.success(records);
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error("获取异常考勤记录失败: " + e.getMessage());
        }
    }
    
    // 获取异常统计信息
    public Result<Map<String, Object>> getExceptionStatistics(String month) {
        try {
            if (month == null || month.isEmpty()) {
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
                month = sdf.format(new Date());
            }
            
            Map<String, Object> result = new HashMap<>();
            
            QueryWrapper<AttendanceRecord> wrapper = new QueryWrapper<>();
            wrapper.apply("DATE_FORMAT(attendance_date, '%Y-%m') = {0}", month);
            
            // 统计总异常数
            wrapper.and(w -> w.eq("is_late", true)
                    .or().eq("is_early_leave", true)
                    .or().eq("is_absent", true));
            Long totalExceptions = attendanceMapper.selectCount(wrapper);
            
            // 统计迟到数
            QueryWrapper<AttendanceRecord> lateWrapper = new QueryWrapper<>();
            lateWrapper.eq("is_late", true);
            lateWrapper.apply("DATE_FORMAT(attendance_date, '%Y-%m') = {0}", month);
            Long lateCount = attendanceMapper.selectCount(lateWrapper);
            
            // 统计早退数
            QueryWrapper<AttendanceRecord> earlyLeaveWrapper = new QueryWrapper<>();
            earlyLeaveWrapper.eq("is_early_leave", true);
            earlyLeaveWrapper.apply("DATE_FORMAT(attendance_date, '%Y-%m') = {0}", month);
            Long earlyLeaveCount = attendanceMapper.selectCount(earlyLeaveWrapper);
            
            // 统计缺勤数
            QueryWrapper<AttendanceRecord> absentWrapper = new QueryWrapper<>();
            absentWrapper.eq("is_absent", true);
            absentWrapper.apply("DATE_FORMAT(attendance_date, '%Y-%m') = {0}", month);
            Long absentCount = attendanceMapper.selectCount(absentWrapper);
            
            // 统计未处理异常数
            QueryWrapper<AttendanceRecord> unhandledWrapper = new QueryWrapper<>();
            unhandledWrapper.and(w -> w.eq("is_late", true)
                    .or().eq("is_early_leave", true)
                    .or().eq("is_absent", true));
            unhandledWrapper.and(w -> w.isNull("exception_status").or().eq("exception_status", "UNHANDLED"));
            unhandledWrapper.apply("DATE_FORMAT(attendance_date, '%Y-%m') = {0}", month);
            Long unhandledCount = attendanceMapper.selectCount(unhandledWrapper);
            
            // 统计已处理异常数
            QueryWrapper<AttendanceRecord> handledWrapper = new QueryWrapper<>();
            handledWrapper.and(w -> w.eq("is_late", true)
                    .or().eq("is_early_leave", true)
                    .or().eq("is_absent", true));
            handledWrapper.eq("exception_status", "HANDLED");
            handledWrapper.apply("DATE_FORMAT(attendance_date, '%Y-%m') = {0}", month);
            Long handledCount = attendanceMapper.selectCount(handledWrapper);
            
            result.put("totalExceptions", totalExceptions);
            result.put("lateCount", lateCount);
            result.put("earlyLeaveCount", earlyLeaveCount);
            result.put("absentCount", absentCount);
            result.put("unhandledCount", unhandledCount);
            result.put("handledCount", handledCount);
            result.put("month", month);
            
            return Result.success(result);
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error("获取异常统计失败: " + e.getMessage());
        }
    }
    
    // 处理异常考勤记录
    public Result<String> handleException(Long recordId, Long handlerId, String status, String remark) {
        try {
            AttendanceRecord record = attendanceMapper.selectById(recordId);
            if (record == null) {
                return Result.error("记录不存在");
            }
            
            // 验证是否为异常记录
            if (record.getIsLate() == null && record.getIsEarlyLeave() == null && record.getIsAbsent() == null) {
                return Result.error("该记录不是异常记录");
            }
            if (record.getIsLate() != null && !record.getIsLate() 
                && record.getIsEarlyLeave() != null && !record.getIsEarlyLeave()
                && record.getIsAbsent() != null && !record.getIsAbsent()) {
                return Result.error("该记录不是异常记录");
            }
            
            // 验证状态
            if (!"HANDLED".equals(status) && !"IGNORED".equals(status) && !"UNHANDLED".equals(status)) {
                return Result.error("无效的处理状态");
            }
            
            record.setExceptionStatus(status);
            record.setExceptionHandlerId(handlerId);
            record.setExceptionHandleTime(new Date());
            if (remark != null && !remark.isEmpty()) {
                record.setExceptionHandleRemark(remark);
            }
            
            attendanceMapper.updateById(record);
            return Result.success("处理成功");
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error("处理失败: " + e.getMessage());
        }
    }
    
    // 导出考勤统计数据
    public void exportAttendanceStatistics(HttpServletResponse response, String month) throws Exception {
        if (month == null || month.isEmpty()) {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
            month = sdf.format(new Date());
        }
        
        Result<Map<String, Object>> statisticsResult = getAttendanceStatistics(month);
        Map<String, Object> data = statisticsResult.getData();
        
        List<Map<String, Object>> details = (List<Map<String, Object>>) data.get("details");
        if (details == null) {
            details = new ArrayList<>();
        }
        
        // 准备导出数据
        List<Map<String, Object>> exportData = new ArrayList<>();
        for (Map<String, Object> detail : details) {
            Map<String, Object> row = new HashMap<>();
            row.put("userName", detail.get("userName") != null ? detail.get("userName").toString() : "员工" + detail.get("userId"));
            row.put("checkInCount", detail.get("checkInCount") != null ? detail.get("checkInCount") : 0);
            row.put("leaveDays", detail.get("leaveDays") != null ? detail.get("leaveDays") : 0);
            row.put("overtimeHours", detail.get("overtimeHours") != null ? detail.get("overtimeHours") : 0);
            row.put("attendanceRate", detail.get("attendanceRate") != null ? detail.get("attendanceRate") + "%" : "0%");
            exportData.add(row);
        }
        
        // 表头
        String[] headers = {"员工姓名", "打卡次数", "请假天数", "加班时长(小时)", "出勤率"};
        String[] fieldNames = {"userName", "checkInCount", "leaveDays", "overtimeHours", "attendanceRate"};
        
        // 导出Excel
        com.ygswglxt.attendance.util.ExcelExportUtil.exportExcel(
            response, 
            "考勤统计_" + month, 
            headers, 
            exportData, 
            fieldNames
        );
    }
    
    // 导出异常考勤记录
    public void exportExceptionRecords(HttpServletResponse response, Long userId, String month, 
                                       String exceptionType, String exceptionStatus) throws Exception {
        Result<List<AttendanceRecord>> recordsResult = getExceptionRecords(userId, month, exceptionType, exceptionStatus);
        List<AttendanceRecord> records = recordsResult.getData();
        if (records == null) {
            records = new ArrayList<>();
        }
        
        // 准备导出数据
        List<Map<String, Object>> exportData = new ArrayList<>();
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        SimpleDateFormat dateTimeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        
        for (AttendanceRecord record : records) {
            Map<String, Object> row = new HashMap<>();
            row.put("userName", record.getUserName() != null ? record.getUserName() : "员工" + record.getUserId());
            row.put("attendanceDate", record.getAttendanceDate() != null ? dateFormat.format(record.getAttendanceDate()) : "");
            
            // 异常类型
            StringBuilder exceptionTypes = new StringBuilder();
            if (record.getIsLate() != null && record.getIsLate()) {
                exceptionTypes.append("迟到").append(record.getLateMinutes() != null ? record.getLateMinutes() + "分钟" : "").append(" ");
            }
            if (record.getIsEarlyLeave() != null && record.getIsEarlyLeave()) {
                exceptionTypes.append("早退").append(record.getEarlyLeaveMinutes() != null ? record.getEarlyLeaveMinutes() + "分钟" : "").append(" ");
        }
            if (record.getIsAbsent() != null && record.getIsAbsent()) {
                exceptionTypes.append("缺勤 ");
            }
            row.put("exceptionType", exceptionTypes.toString().trim());
            
            row.put("exceptionReason", record.getExceptionReason() != null ? record.getExceptionReason() : "");
            row.put("checkInTime", record.getCheckInTime() != null ? dateTimeFormat.format(record.getCheckInTime()) : "");
            row.put("checkOutTime", record.getCheckOutTime() != null ? dateTimeFormat.format(record.getCheckOutTime()) : "");
            
            // 处理状态
            String status = "未处理";
            if (record.getExceptionStatus() != null) {
                if ("HANDLED".equals(record.getExceptionStatus())) {
                    status = "已处理";
                } else if ("IGNORED".equals(record.getExceptionStatus())) {
                    status = "已忽略";
                }
            }
            row.put("exceptionStatus", status);
            row.put("exceptionHandleRemark", record.getExceptionHandleRemark() != null ? record.getExceptionHandleRemark() : "");
            row.put("exceptionHandleTime", record.getExceptionHandleTime() != null ? dateTimeFormat.format(record.getExceptionHandleTime()) : "");
            
            exportData.add(row);
        }
        
        // 表头
        String[] headers = {"员工姓名", "考勤日期", "异常类型", "异常原因", "上班时间", "下班时间", "处理状态", "处理备注", "处理时间"};
        String[] fieldNames = {"userName", "attendanceDate", "exceptionType", "exceptionReason", "checkInTime", "checkOutTime", "exceptionStatus", "exceptionHandleRemark", "exceptionHandleTime"};
        
        // 导出Excel
        String fileName = "考勤异常记录";
        if (month != null && !month.isEmpty()) {
            fileName += "_" + month;
        }
        com.ygswglxt.attendance.util.ExcelExportUtil.exportExcel(
            response, 
            fileName, 
            headers, 
            exportData, 
            fieldNames
        );
    }
    
    // 获取指定月份每天的打卡次数（用于趋势图）
    public List<Map<String, Object>> getDailyCheckInsByMonth(String month) {
        try {
            if (month == null || month.isEmpty()) {
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
                month = sdf.format(new Date());
            }
            return attendanceMapper.selectDailyCheckInsByMonth(month);
        } catch (Exception e) {
            e.printStackTrace();
            return new ArrayList<>();
        }
    }
}

